using System.Activities;
using System.Activities.Statements;
using System.Collections.Generic;
using System.Linq;
using Headsight.BPMN2WF.Transformation;

namespace Headsight.BPMN2WF.WF.Simplification
{
    /// <summary>
    /// <see cref="IWFSimplifier"/> implementation simplifying the <see cref="Sequence"/> of the <i>Then branches</i>
    /// of <see cref="If"/> activities by combining any eventual child <see cref="Sequence"/>s of the respective
    /// <i>Then branch</i> <see cref="Sequence"/> into the parent <i>Then branch</i> <see cref="Sequence"/>.
    /// 
    /// This is a works for now implementation... Anyhow I've the feeling that this is not the right abstraction level
    /// to do this kind of simplifications. Somehow the respective <i>WF artifacts</i> are of <i>lower abstraction</i>
    /// then the most other <see cref="IWFSimplifier"/> are operating.
    /// </summary>
    public class WFSimplifierIfThenSequence : IWFSimplifier
    {
        public BPMNTransformationResult Simplify(IBPMN2WFTransformationContext ctx, BPMNTransformationResult transformationResult)
        {
            if (transformationResult.Result is Sequence)
            {
                Simplify((Sequence)transformationResult.Result);
            }

            if (transformationResult.Result is Flowchart)
            {
                Simplify((Flowchart) transformationResult.Result);
            }

            return transformationResult;
        }

        public bool Probe(IBPMN2WFTransformationContext ctx, BPMNTransformationResult transformationResult)
        {
            return true;
        }

        private static void Simplify(Sequence sequence)
        {
            foreach (var each in sequence.Activities)
            {
                if (each is If && ((If)each).Then is Sequence)
                {
                    ((If) each).Then = SimplifyInt((Sequence)((If) each).Then);
                }
            }
        }

        private static Sequence SimplifyInt(Sequence sequence)
        {
            var activites = new List<Activity>(sequence.Activities);
            sequence.Activities.Clear();

            foreach (var each in activites)
            {
                if (each is Sequence)
                {
                    foreach (var each2 in ((Sequence)each).Activities)
                    {
                        sequence.Activities.Add(each2);
                    }
                }
                else
                {
                    sequence.Activities.Add(each);
                }
            }

            return sequence;
        }

        private static void Simplify(Flowchart flowchart)
        {
            foreach (var each in flowchart.Nodes.OfType<FlowStep>().Select(x => x.Action).OfType<If>().Where(x => x.Then is Sequence))
            {
                SimplifyInt((Sequence) each.Then);
            }
        }
    }
}